// Generator 配合 Promise 的异步方案

function ajax (url) {
    return new Promise(function (resolve, reject) {
        //AJAX请求
        var xhr = new XMLHttpRequest()
        //请求方式和地址
        xhr.open('GET', url)
        //请求类型
        //获取结果为json对象而不是字符串
        xhr.responseType = 'json'
        //请求完成过后执行
        xhr.onload = function () {
            if (this.status === 200) {
                //请求成功 返回请求的结果
                resolve(this.response)
            } else {
                //请求失败 返回错误信息 即当前状态文本
                reject(new Error(this.statusText))
            }
        }
        //开始执行异步请求
        xhr.send()
    }) 
}

function * main () {
    try {
        const users = yield ajax('/api/users.json')
        console.log(users);

        const posts = yield ajax('api/posts.json')
        console.log(posts);
    } catch (e) {
        //捕获执行的异常
        console.log(e);
    }
    
}

// const g = main()

// //递归函数
// function handleResult (result) {
//     if (result.done) return  //生成器函数结束

//     //未结束则执行回调函数 将结果传给生成器函数 使其继续执行
//     result.value.then(data => {
//         handleResult(g.next(data))
//         //处理失败的回调错误
//     }, error => {
//         //在生成器内生成一个异常
//         g.throw(error)
//     })
// }

// //生成器函数第一次调用结果
// handleResult(g.next())

//方便复用 可以封装成一个公共的函数 可以用于任一个生成器函数
function co (generator) {
    const g = generator()

    //递归函数
    function handleResult (result) {
        if (result.done) return  //生成器函数结束

        //未结束则执行回调函数 将结果传给生成器函数 使其继续执行
        result.value.then(data => {
            handleResult(g.next(data))
            //处理失败的回调错误
        }, error => {
            //在生成器内生成一个异常
            g.throw(error)
        })
    }

    //生成器函数第一次调用结果
    handleResult(g.next())
}

//有更为完善的co库
co(main)


// //此时 yield 返回对象的value就是返回的promise对象
// const result = g.next()

// //此时执行返回的promise的回调函数 可以拿到promise的执行结果
// //使用递归的方式不断迭代 直到生成器函数执行结束过后结束递归
// result.value.then(data => {
//     //将得到的结果传给生成器函数 该函数则会继续往下执行 并且传入的数据会作为yield的返回值
//     const result2 = g.next(data);

//     //查看生成器函数内是否执行完毕 执行完毕则返回不再继续
//     if (result2.done) return 

//     result2.value.then(data => {
//         const result3 = g.next(data);

//         //查看生成器函数内是否执行完毕 执行完毕则返回不再继续
//         if (result3.done) return 

//         result3.value.then(data => {
//         g.next(data)
//         })
//     })
// })
